// src/utils/userUtils.js

const moment = require("moment");
const sqlconfig = require("../mysql/config");

/**
 * 生成设备标识符
 * @param {Object} req - Express请求对象
 * @returns {string} 设备标识符
 */
const generateDeviceIdentifier = (req) => {
  const ip = req.ip || req.connection.remoteAddress;
  const userAgent = req.headers["user-agent"] || "";
  return `${ip}-${userAgent}`;
};

/**
 * 存储token到数据库
 * @param {string} userId - 用户ID
 * @param {string} token - JWT token
 * @param {string} ip - IP地址
 * @param {string} userAgent - 用户代理字符串
 * @param {string} loginSystem - 登录系统
 * @returns {Promise} 存储操作的Promise
 */
const storeToken = (userId, token, ip, userAgent, loginSystem) => {
  return new Promise((resolve, reject) => {
    // 首先删除该用户在该系统中的所有旧 token
    const deleteSql = `
      DELETE FROM tokens 
      WHERE user_id = ? AND login_system = ?
    `;
    
    sqlconfig.query(deleteSql, [userId, loginSystem], (deleteError) => {
      if (deleteError) {
        console.error("Error deleting old tokens:", deleteError);
        reject(deleteError);
        return;
      }

      // 插入新的 token
      const insertSql = `
        INSERT INTO tokens (user_id, token, ip_address, user_agent, login_system, expires_at)
        VALUES (?, ?, ?, ?, ?, DATE_ADD(NOW(), INTERVAL 1 HOUR))
      `;

      sqlconfig.query(insertSql, [userId, token, ip, userAgent, loginSystem], (insertError, insertResult) => {
        if (insertError) {
          console.error("Error inserting new token:", insertError);
          reject(insertError);
        } else {
          resolve(insertResult);
        }
      });
    });
  });
};

/**
 * 删除旧的token
 * @param {string} userId - 用户ID
 * @param {string} loginSystem - 用户登录系统
 * @param {string} ip - IP地址
 * @param {string} userAgent - 用户代理字符串
 * @returns {Promise} 删除操作的Promise
 */
const deleteOldTokens = (userId, loginSystem, ip, userAgent) => {
  return new Promise((resolve, reject) => {
    const sql = `DELETE FROM tokens WHERE user_id = ? AND login_system = ? AND (ip_address != ? OR user_agent != ?)`;
    sqlconfig.query(sql, [userId, loginSystem, ip, userAgent], (error, results) => {
      if (error) {
        console.error("Error deleting old tokens:", error);
        reject(error);
      } else {
        resolve(results);
      }
    });
  });
};

/**
 * 格式化日期时间
 * @param {Date} date - 日期对象
 * @returns {string} 格式化后的日期时间字符串
 */
const formatDateTime = (date) => {
  return moment(date).format('YYYY-MM-DD HH:mm:ss');
};

/**
 * 清理数据库中的过期token
 * @returns {void} 此函数不返回值
 * @description 此函数会删除数据库中所有过期的token记录。
 * 它通过比较当前时间和token的过期时间来确定哪些token已过期。
 * 此函数通常被设置为定期自动运行，以保持数据库的整洁和高效。
 */
const cleanExpiredTokens = () => {
  const sql = "DELETE FROM tokens WHERE expires_at < NOW()";
  sqlconfig.query(sql, (error, results) => {
    if (error) {
      console.error("Error cleaning expired tokens:", error);
    } else {
      console.log("Cleaned expired tokens:", results.affectedRows);
    }
  });
};

/**
 * 构建树形菜单结构
 * @param {Array} menus - 菜单数组
 * @param {number|null} parentId - 父菜单ID
 * @returns {Array} 树形结构的菜单数组
 */
function buildMenuTree(menus, parentId = null) {
  return menus
    .filter((menu) => menu.parentId === parentId)
    .map((menu) => {
      const children = buildMenuTree(menus, menu.id);
      const menuItem = {
        ...menu,
        children: children, // 总是添加 children 字段，即使它可能是空数组
      };

      // 如果有子菜单，删除 component 字段
      if (children.length > 0) {
        delete menuItem.component;
      }

      return menuItem;
    })
    .sort((a, b) => a.sortOrder - b.sortOrder);
}

module.exports = {
  generateDeviceIdentifier,
  storeToken,
  deleteOldTokens,
  formatDateTime,
  cleanExpiredTokens,
  buildMenuTree
};